package com.ehe.common.core.web.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ehe.common.core.web.pojo.domain.SuperEntity;
import com.ehe.common.core.web.pojo.dto.BaseSearchable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 基础service
 * @param <T> 泛型
 * @author jerry
 */
public interface MybatisService<T extends SuperEntity<T, PK>, PK extends Serializable> {

    /**
     * 创建 wrapper 查询条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> createQueryWrapper();

    /**
     * 创建 wrapper 查询条件
     * @param pageable 分页条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> createQueryWrapper(Pageable pageable);

    /**
     * 创建 wrapper 查询条件
     * @param sort 排序条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> createQueryWrapper(Sort sort);

    /**
     * 创建 wrapper 查询条件
     * @param baseSearchable 查询条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> createQueryWrapper(BaseSearchable baseSearchable);

    /**
     * 创建 wrapper 查询条件
     * @param pageable 分页条件
     * @param baseSearchable 查询条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> createQueryWrapper(Pageable pageable, BaseSearchable baseSearchable);

    /**
     * 创建 wrapper 查询条件
     * @param sort 排序条件
     * @param baseSearchable 查询条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> createQueryWrapper(Sort sort, BaseSearchable baseSearchable);

    /**
     * 将分页参数的排序规则添加到 wrapper 查询条件中
     * @param queryWrapper 查询条件
     * @param pageable 分页条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> addQueryWrapper(QueryWrapper<T> queryWrapper, Pageable pageable);

    /**
     * 将排序规则添加到 wrapper 查询条件中
     * @param queryWrapper 查询条件
     * @param sort 排序规则
     * @return wrapper 查询条件
     */
    QueryWrapper<T> addQueryWrapper(QueryWrapper<T> queryWrapper, Sort sort);

    /**
     * 将 searchable 添加到 wrapper 查询条件中
     * @param queryWrapper 查询条件
     * @param baseSearchable 查询条件
     * @return wrapper 查询条件
     */
    QueryWrapper<T> addQueryWrapper(QueryWrapper<T> queryWrapper, BaseSearchable baseSearchable);

    /**
     * 将 searchable 添加到 wrapper 查询条件中
     * @param queryWrapper 查询条件
     * @param baseSearchable 查询条件
     */
    void addQueryWrapper(LambdaQueryWrapper<T> queryWrapper, BaseSearchable baseSearchable);

    /**
     * 插入一条记录
     *
     * @param entity 实体对象
     */
    int insert(T entity);

    /**
     * 批量新增数据,自选字段 insert
     * {@link com.baomidou.mybatisplus.extension.injector.methods.additional.InsertBatchSomeColumn}
     * @param entityList 实体集合
     * @return 插入条数
     */
    int insertBatchSomeColumn(List<T> entityList);

    /**
     * 批量新增(集合数据自动拆分上传)
     * @param entityList 实体集合
     * @return 插入条数
     */
    int insertBatch(List<T> entityList);

    /**
     * 批量新增
     * @param entityList 实体集合
     * @param limit 实体集合
     * @return 插入条数
     */
    int insertBatch(List<T> entityList, int limit);

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     */
    int deleteById(PK id);

    /**
     * 根据 columnMap 条件，删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    int deleteByMap(Map<String, Object> columnMap);

    /**
     * 根据 entity 条件，删除记录
     *
     * @param wrapper 实体对象封装操作类（可以为 null）
     */
    int delete(Wrapper<T> wrapper);

    /**
     * 删除（根据ID 批量删除）
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    int deleteBatchIds(Collection<? extends PK> idList);

    /**
     * 根据 ID 修改
     *
     * @param entity 实体对象
     */
    int updateById(T entity);

    /**
     * 根据 whereEntity 条件，更新记录
     *
     * @param entity        实体对象 (set 条件值,可以为 null)
     * @param updateWrapper 实体对象封装操作类（可以为 null,里面的 entity 用于生成 where 语句）
     */
    int update(T entity, Wrapper<T> updateWrapper);

    /**
     * 全字段更新
     * {@link com.baomidou.mybatisplus.extension.injector.methods.additional.AlwaysUpdateSomeColumnById}
     * @param entity 实体
     * @return 更新条数
     */
    int alwaysUpdateSomeColumnById(T entity);

    /**
     * 根据 ID 查询
     * @param id 主键ID
     * @return 实体
     */
    T selectById(PK id);

    /**
     * 根据 ID 查询
     * @param id 主键ID
     * @return 实体
     */
    Optional<T> selectByIdOptional(PK id);

    /**
     * 查询（根据ID 批量查询）
     * @param idList 主键ID列表(不能为 null 以及 empty)
     * @return 实体集合
     */
    List<T> selectBatchIds(Collection<? extends PK> idList);

    /**
     * 查询（根据 columnMap 条件）
     * @param columnMap 表字段 map 对象
     * @return 实体集合
     */
    List<T> selectByMap(Map<String, Object> columnMap);

    /**
     * 查询一条记录
     * @param sort 排序规则
     * @param baseSearchable 查询条件
     * @return 实体集合
     */
    T selectOne(Sort sort, BaseSearchable baseSearchable);

    /**
     * 查询一条记录
     * @param sort 排序规则
     * @param baseSearchable 查询条件
     * @return 实体集合
     */
    Optional<T> selectOneOptional(Sort sort, BaseSearchable baseSearchable);

    /**
     * 根据 Wrapper 条件，查询一条记录
     * @param queryWrapper 实体对象封装操作类（可以为 null）
     */
    T selectOne(Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件，查询一条记录
     * @param queryWrapper 实体对象封装操作类（可以为 null）
     */
    Optional<T> selectOneOptional(Wrapper<T> queryWrapper);

    /**
     * 查询总记录数
     * @param baseSearchable 查询条件
     * @return 实体集合
     */
    Integer selectCount(BaseSearchable baseSearchable);

    /**
     * 根据 Wrapper 条件，查询总记录数
     * @param queryWrapper 实体对象封装操作类（可以为 null）
     */
    Integer selectCount(Wrapper<T> queryWrapper);

    /**
     * 实体集合查询
     * @param baseSearchable 查询条件
     * @return 实体集合
     */
    List<T> selectList(BaseSearchable baseSearchable);

    /**
     * 实体集合查询
     * @param sort 排序规则
     * @param baseSearchable 查询条件
     * @return 实体集合
     */
    List<T> selectList(Sort sort, BaseSearchable baseSearchable);

    /**
     * 根据 Wrapper 条件，实体集合查询
     * @param queryWrapper 实体对象封装操作类（可以为 null）
     */
    List<T> selectList(Wrapper<T> queryWrapper);

    /**
     * 根据查询条件，查询分页记录
     * @param pageable 分页条件
     * @param baseSearchable 查询条件
     * @return 分页数据
     */
    Page<T> selectPage(Pageable pageable, BaseSearchable baseSearchable);

    /**
     * 根据查询条件，查询分页记录
     * @param pageable 分页条件
     * @return 分页数据
     */
    Page<T> selectPage(Pageable pageable);

}
